package sqlite3

//
//import (
//	"bufio"
//	"bytes"
//	"encoding/json"
//	"fmt"
//	"gitee.com/daka1004/devops-runner/dto"
//	"gitee.com/daka1004/devops-runner/models"
//	"gitee.com/daka1004/devops-runner/modules/setting"
//	"github.com/gorilla/websocket"
//	"golang.org/x/text/encoding/simplifiedchinese"
//	"golang.org/x/text/transform"
//	"io"
//	"io/ioutil"
//	"os"
//	"os/exec"
//	"path/filepath"
//	"strings"
//	"sync"
//	"time"
//)
//
//type RunnerService struct{}
//
////
////// 方法二：使用 strings.Builder
////var out bytes.Buffer
//////cmd.Stdout = &out
//////cmd.Stdout = logFile
//////cmd.Stderr = logFile
////// 执行命令
////cmd.Stdout = io.MultiWriter(&out, logFile)
////cmd.Stderr = logFile
////
////err = cmd.Run()
////if err != nil {
////	// 如果命令执行出错，输出错误信息并终止测试
////	fmt.Println("命令执行出错: %v", err)
////}
////
////task.Status = models.StatusSuccess
////fmt.Println("out", out.String())
//////db.UpdateTask(task)
////fmt.Println("sendCallback before ")
//////sendCallback(task)
////outputBytes := out.Bytes()
////// 判断操作系统，如果是 Windows 则进行编码转换
////if os.PathSeparator == '\\' {
////	decoder := simplifiedchinese.GBK.NewDecoder()
////	_, _, _ = transform.String(decoder, out.String())
////
////}
////
////fmt.Println("out", string(outputBytes))
//////db.UpdateTask(task)
////fmt.Println("sendCallback before ")
////sendCallback(task)
//// 创建一个用于停止 tailLog 的通道
//
//// 启动 tailLog 函数的 goroutine
//// tailLog(task.LogPath, setting.ServerIP, req.ExecuteID, 8280)
//// 发送停止信号给 tailLog 函数
//// 自定义Writer，用于将输出同时写入日志文件和控制台
//type ConsoleAndLogWriter struct {
//	logFile *os.File
//	mu      sync.Mutex
//}
//
//func (w *ConsoleAndLogWriter) Write(p []byte) (n int, err error) {
//	w.mu.Lock()
//	defer w.mu.Unlock()
//	// 先在控制台打印
//	fmt.Print(string(p))
//	// 再写入日志文件
//	return w.logFile.Write(p)
//}
//
//func (r RunnerService) Execute2(req dto.RunnerPipeline) (int64, interface{}, error) {
//
//	//func executePipeline(w http.ResponseWriter, r *http.Request) {
//
//	task := &models.Task{
//		PipelineID: req.PipelineID,
//		ExecuteID:  req.ExecuteID,
//		Command:    req.Command,
//		Status:     models.StatusRunning,
//		Serial:     req.Serial, //默认不能重复
//	}
//	fmt.Println("--------------task------------", task, task.ExecuteID)
//	/*exists, _ := db.IsTaskExists(task)
//	if err := db.CreateTask(task); err != nil {
//		//http.Error(w, "Failed to create task", http.StatusInternalServerError)
//		log.Println("err create task")
//		return 0, "Failed to create task", http.ErrNotMultipart
//	}*/
//
//	//go func() {
//	//if !exists {
//	task.Workspace = createWorkspace(task.ExecuteID)
//	task.LogPath = filepath.Join(task.Workspace, "run.log")
//	task.Status = models.StatusRunning
//	//}
//	fmt.Println("logpath     ", task.LogPath)
//	fmt.Println("workspace     ", task.Workspace)
//	// 创建用于停止日志读取的通道
//	stopChan := make(chan struct{})
//
//	// 创建用于通知主线程日志读取完成的通道
//	doneChan := make(chan struct{})
//	// 创建用于等待所有goroutine完成的WaitGroup
//	//var wg sync.WaitGroup
//	// 创建临时脚本文件
//	scriptPath, err := createScriptFile(task.Workspace, task.Command, req.NodeUuid)
//	if err != nil {
//		handleError(task, err)
//		return 0, nil, err
//	}
//	fmt.Println(scriptPath)
//	//defer os.Remove(scriptPath) // 执行后删除脚本
//	// 启动日志读取协程
//
//	/*
//		stopChan := make(chan struct{})
//		go tailLog(task.LogPath, setting.Setting.ServerIP, req.ExecuteID, 8280, stopChan)*/
//	logFile, err := os.Create(task.LogPath)
//	if err != nil {
//		handleError(task, err)
//		return 0, nil, err
//	}
//	defer logFile.Close()
//
//	cmd, err := prepareCommand(scriptPath)
//	cmd.Dir = task.Workspace
//	fmt.Println("prepareCommand after ")
//	if err != nil {
//		handleError(task, err)
//		return 0, nil, err
//	}
//
//	var out bytes.Buffer
//
//	// 创建自定义Writer，用于同时写入控制台和日志文件
//	consoleAndLogWriter := &ConsoleAndLogWriter{logFile: logFile}
//
//	if os.PathSeparator == '\\' {
//		// Windows 系统：实时转换 GBK 到 UTF-8
//		stdout, err := cmd.StdoutPipe()
//		if err != nil {
//			logFile.WriteString(fmt.Sprintf("获取标准输出管道失败: %v\n", err))
//			return 0, nil, err
//		}
//
//		stderr, err := cmd.StderrPipe()
//		if err != nil {
//			logFile.WriteString(fmt.Sprintf("获取标准错误管道失败: %v\n", err))
//			return 0, nil, err
//		}
//
//		// 启动命令
//		if err := cmd.Start(); err != nil {
//			logFile.WriteString(fmt.Sprintf("启动命令失败: %v\n", err))
//			handleError(task, err)
//
//			// 在返回前关闭停止通道，通知日志读取协程停止
//			close(stopChan)
//
//			// 等待日志读取协程完成
//			<-doneChan
//
//			return 0, nil, err
//		}
//
//		// 增加等待组计数，表示有两个goroutine需要等待
//		//wg.Add(2)
//
//		// 异步处理标准输出（实时转换）
//		go func() {
//			//defer wg.Done()
//			decoder := simplifiedchinese.GBK.NewDecoder()
//			reader := transform.NewReader(stdout, decoder)
//
//			// 使用流式读取和写入，而不是一次性读取所有内容
//			buffer := make([]byte, 4096)
//			for {
//				n, err := reader.Read(buffer)
//				if n > 0 {
//					// 先写入内存缓冲区
//					out.Write(buffer[:n])
//					// 再写入日志文件和控制台
//					_, err := consoleAndLogWriter.Write(buffer[:n])
//					if err != nil {
//						logFile.WriteString(fmt.Sprintf("写入标准输出失败: %v\n", err))
//						break
//					}
//				}
//				if err != nil {
//					if err != io.EOF {
//						logFile.WriteString(fmt.Sprintf("处理标准输出失败: %v\n", err))
//					}
//					break
//				}
//			}
//		}()
//
//		// 异步处理标准错误（实时转换）
//		go func() {
//			//defer wg.Done()
//			decoder := simplifiedchinese.GBK.NewDecoder()
//			reader := transform.NewReader(stderr, decoder)
//
//			// 使用流式读取和写入，而不是一次性读取所有内容
//			buffer := make([]byte, 4096)
//			for {
//				n, err := reader.Read(buffer)
//				if n > 0 {
//					// 先写入内存缓冲区
//					out.Write(buffer[:n])
//					// 再写入日志文件和控制台
//					_, err := consoleAndLogWriter.Write(buffer[:n])
//					if err != nil {
//						logFile.WriteString(fmt.Sprintf("写入标准错误失败: %v\n", err))
//						break
//					}
//				}
//				if err != nil {
//					if err != io.EOF {
//						logFile.WriteString(fmt.Sprintf("处理标准错误失败: %v\n", err))
//					}
//					break
//				}
//			}
//		}()
//	} else {
//		// Linux/Mac 系统：直接使用 MultiWriter
//		cmd.Stdout = io.MultiWriter(&out, consoleAndLogWriter)
//		cmd.Stderr = io.MultiWriter(&out, consoleAndLogWriter)
//
//		// 启动命令
//		if err := cmd.Start(); err != nil {
//			logFile.WriteString(fmt.Sprintf("启动命令失败: %v\n", err))
//			handleError(task, err)
//
//			// 在返回前关闭停止通道，通知日志读取协程停止
//			close(stopChan)
//
//			// 等待日志读取协程完成
//			<-doneChan
//
//			return 0, nil, err
//		}
//	}
//
//	// 增加等待组计数，表示有一个goroutine需要等待
//	//wg.Add(1)
//
//	go func() {
//		//defer wg.Done()
//		tailLog(task.LogPath, setting.Setting.ServerIP, req.ExecuteID, 8280, stopChan)
//		// 日志读取完成后发送通知
//		doneChan <- struct{}{}
//	}()
//	//go func() {
//	//	// 日志读取完成后发送通知
//	//	doneChan <- struct{}{}
//	//}()
//	// 增加等待组计数，表示有一个goroutine需要等待
//	//wg.Add(1)
//
//	// 异步等待命令完成
//	go func() {
//		//defer wg.Done()
//		err := cmd.Wait() // 这将阻塞直到脚本及其所有子进程完成
//
//		if err != nil {
//			logFile.WriteString(fmt.Sprintf("命令执行出错: %v\n", err))
//			fmt.Printf("命令执行出错: %v\n", err)
//			//close(stopChan)
//			// 可以在这里处理错误状态
//		} else {
//			logFile.WriteString("命令执行成功完成\n")
//			fmt.Println("命令执行成功完成")
//		}
//
//		// 无论成功或失败，都关闭停止通道
//		close(stopChan)
//	}()
//
//	// 等待所有goroutine完成
//	//wg.Wait()
//
//	fmt.Println("命令执行完成，日志已以 UTF - 8 编码写入", task.LogPath)
//	return 0, nil, nil
//}
//func (r RunnerService) Execute(req dto.RunnerPipeline) (int64, interface{}, error) {
//
//	//func executePipeline(w http.ResponseWriter, r *http.Request) {
//
//	task := &models.Task{
//		PipelineID: req.PipelineID,
//		ExecuteID:  req.ExecuteID,
//		Command:    req.Command,
//		Status:     models.StatusRunning,
//		Serial:     req.Serial, //默认不能重复
//	}
//	fmt.Println("--------------task------------", task, task.ExecuteID)
//	/*exists, _ := db.IsTaskExists(task)
//	if err := db.CreateTask(task); err != nil {
//		//http.Error(w, "Failed to create task", http.StatusInternalServerError)
//		log.Println("err create task")
//		return 0, "Failed to create task", http.ErrNotMultipart
//	}*/
//
//	//go func() {
//	//if !exists {
//	task.Workspace = createWorkspace(task.ExecuteID)
//	task.LogPath = filepath.Join(task.Workspace, "run.log")
//	task.Status = models.StatusRunning
//	//}
//	fmt.Println("logpath     ", task.LogPath)
//	fmt.Println("workspace     ", task.Workspace)
//	// 创建用于停止日志读取的通道
//	stopChan := make(chan struct{})
//
//	// 创建用于通知主线程日志读取完成的通道
//	doneChan := make(chan struct{})
//	// 创建临时脚本文件
//	scriptPath, err := createScriptFile(task.Workspace, task.Command, req.NodeUuid)
//	if err != nil {
//		handleError(task, err)
//		return 0, nil, err
//	}
//	fmt.Println(scriptPath)
//	//defer os.Remove(scriptPath) // 执行后删除脚本
//	// 启动日志读取协程
//
//	/*
//		stopChan := make(chan struct{})
//		go tailLog(task.LogPath, setting.Setting.ServerIP, req.ExecuteID, 8280, stopChan)*/
//	logFile, err := os.Create(task.LogPath)
//	if err != nil {
//		handleError(task, err)
//		return 0, nil, err
//	}
//	defer logFile.Close()
//
//	cmd, err := prepareCommand(scriptPath)
//	cmd.Dir, _ = os.Getwd()
//	//cmd.Dir = task.Workspace
//	fmt.Println("prepareCommand after ")
//	if err != nil {
//		handleError(task, err)
//		return 0, nil, err
//	}
//
//	var out bytes.Buffer
//	//
//	if os.PathSeparator == '\\' {
//		// Windows 系统：实时转换 GBK 到 UTF-8
//		stdout, err := cmd.StdoutPipe()
//		if err != nil {
//			logFile.WriteString(fmt.Sprintf("获取标准输出管道失败: %v\n", err))
//			return 0, nil, err
//		}
//
//		stderr, err := cmd.StderrPipe()
//		if err != nil {
//			logFile.WriteString(fmt.Sprintf("获取标准错误管道失败: %v\n", err))
//			return 0, nil, err
//		}
//
//		// 启动命令
//		if err := cmd.Start(); err != nil {
//			logFile.WriteString(fmt.Sprintf("启动命令失败: %v\n", err))
//			handleError(task, err)
//			return 0, nil, err
//		}
//
//		// 使用锁保护内存缓冲区和文件写入操作
//		var mu sync.Mutex
//
//		// 异步处理标准输出（实时转换）
//		go func() {
//			decoder := simplifiedchinese.GBK.NewDecoder()
//			reader := transform.NewReader(stdout, decoder)
//			data, err := io.ReadAll(reader)
//			if err != nil {
//				fmt.Printf("处理标准输出失败: %v\n", err)
//				return
//			}
//			mu.Lock()
//			_, err = io.Copy(io.MultiWriter(&out, logFile), bytes.NewReader(data))
//			mu.Unlock()
//			if err != nil {
//				fmt.Printf("写入标准输出失败: %v\n", err)
//			}
//		}()
//
//		// 异步处理标准错误（实时转换）
//		go func() {
//			decoder := simplifiedchinese.GBK.NewDecoder()
//			reader := transform.NewReader(stderr, decoder)
//			data, err := io.ReadAll(reader)
//			if err != nil {
//				fmt.Printf("处理标准错误失败: %v\n", err)
//				return
//			}
//			mu.Lock()
//			_, err = io.Copy(io.MultiWriter(&out, logFile), bytes.NewReader(data))
//			mu.Unlock()
//			if err != nil {
//				fmt.Printf("写入标准错误失败: %v\n", err)
//			}
//		}()
//	} else {
//		// Linux/Mac 系统：直接使用 MultiWriter
//		cmd.Stdout = io.MultiWriter(&out, logFile)
//		cmd.Stderr = io.MultiWriter(&out, logFile)
//
//		// 启动命令
//		if err := cmd.Start(); err != nil {
//			handleError(task, err)
//			return 0, nil, err
//		}
//	}
//
//	/*if os.PathSeparator == '\\' {
//		// Windows 系统：实时转换 GBK 到 UTF-8
//		//stdout, err := cmd.StdoutPipe()
//		cmd.Stdout = io.MultiWriter(&out, logFile)
//
//		if err != nil {
//			logFile.WriteString(fmt.Sprintf("获取标准输出管道失败: %v\n", err))
//			return 0, nil, err
//		}
//
//		stderr, err := cmd.StderrPipe()
//		if err != nil {
//			logFile.WriteString(fmt.Sprintf("获取标准错误管道失败: %v\n", err))
//			return 0, nil, err
//		}
//
//		// 启动命令
//		if err := cmd.Start(); err != nil {
//			logFile.WriteString(fmt.Sprintf("启动命令失败: %v\n", err))
//			handleError(task, err)
//			return 0, nil, err
//		}
//
//		// 使用锁保护内存缓冲区和文件写入操作
//		var mu sync.Mutex
//		//
//		//// 异步处理标准输出（实时转换）
//		//go func() {
//		//	decoder := simplifiedchinese.GBK.NewDecoder()
//		//	reader := transform.NewReader(stdout, decoder)
//		//	data, err := io.ReadAll(reader)
//		//	if err != nil {
//		//		mu.Lock()
//		//		logFile.WriteString(fmt.Sprintf("处理标准输出失败: %v\n", err))
//		//		mu.Unlock()
//		//		return
//		//	}
//		//	mu.Lock()
//		//	_, err = io.Copy(io.MultiWriter(&out, logFile), bytes.NewReader(data))
//		//	mu.Unlock()
//		//	if err != nil {
//		//		logFile.WriteString(fmt.Sprintf("写入标准输出失败: %v\n", err))
//		//	}
//		//}()
//
//		// 异步处理标准错误（实时转换）
//		go func() {
//			decoder := simplifiedchinese.GBK.NewDecoder()
//			reader := transform.NewReader(stderr, decoder)
//			data, err := io.ReadAll(reader)
//			if err != nil {
//				mu.Lock()
//				logFile.WriteString(fmt.Sprintf("处理标准错误失败: %v\n", err))
//				mu.Unlock()
//				return
//			}
//			mu.Lock()
//			_, err = io.Copy(io.MultiWriter(&out, logFile), bytes.NewReader(data))
//			mu.Unlock()
//			if err != nil {
//				logFile.WriteString(fmt.Sprintf("写入标准错误失败: %v\n", err))
//			}
//		}()
//	} else {
//		// Linux/Mac 系统：直接使用 MultiWriter
//		cmd.Stdout = io.MultiWriter(&out, logFile)
//		cmd.Stderr = io.MultiWriter(&out, logFile)
//
//		// 启动命令
//		if err := cmd.Start(); err != nil {
//			logFile.WriteString(fmt.Sprintf("启动命令失败: %v\n", err))
//			handleError(task, err)
//			return 0, nil, err
//		}
//	}*/
//
//	go func() {
//		tailLog(task.LogPath, setting.Setting.ServerIP, req.ExecuteID, 8280, stopChan)
//		// 日志读取完成后发送通知
//		doneChan <- struct{}{}
//	}()
//	// 异步等待命令完成
//	go func() {
//		err := cmd.Wait() // 这将阻塞直到脚本及其所有子进程完成
//
//		if err != nil {
//			fmt.Printf("命令执行出错: %v\n", err)
//			// 可以在这里处理错误状态
//		} else {
//			fmt.Println("命令执行成功完成")
//		}
//
//		// 无论成功或失败，都关闭停止通道
//		close(stopChan)
//	}()
//	// 等待日志协程确认所有日志已处理完毕
//	if err != nil {
//		fmt.Printf("执行命令出错: %v\n", err)
//		return 0, nil, err
//	}
//
//	fmt.Println("命令执行完成，日志已以 UTF - 8 编码写入", task.LogPath)
//	<-doneChan
//	//}()
//	return 0, nil, nil
//}
//
//// // 判断是否需要进行编码转换（假设在 Windows 下可能是 GBK 编码）
////
////	if os.PathSeparator == '\\' {
////		fmt.Println("---------Windows----------")
////		decoder := simplifiedchinese.GBK.NewDecoder()
////		decoded, _, err := transform.Bytes(decoder, out.Bytes())
////		if err != nil {
////			fmt.Printf("编码转换出错: %v\n", err)
////			return 0, nil, err
////		}
////		// 直接将转换后的内容写入日志文件
////		_, err = logFile.Write(decoded)
////		if err != nil {
////			fmt.Printf("写入日志文件出错: %v\n", err)
////			return 0, nil, err
////		}
////	} else {
////
////		// 如果不是 Windows 系统，直接写入原始输出
////		_, err = logFile.Write(out.Bytes())
////		fmt.Println("---------linux----------")
////		if err != nil {
////			fmt.Printf("写入日志文件出错: %v\n", err)
////			return 0, nil, err
////		}
////	}
////
////	if err := cmd.Start(); err != nil {
////		handleError(task, err)
////		close(stopChan)
////		return 0, nil, err
////	}
//func createWorkspace(taskID string) string {
//	/*虽然同一个任务数据隔离可以解决，但是同一个任务会调用多次，并且后面执行依赖前一次的结果，这种情况，如何修改代码？
//	**任务保存到数据库一下，同时目录和保存的流水线记录有关！*/
//	//当前流水线id,查询数据，如果存在记录则不新建workspace 同一个流水线执行多次的问题 随机数拼接拆分为 taskid携带
//	workspace := filepath.Join("workspaces", (taskID))
//	os.MkdirAll(workspace, 0755)
//	fmt.Println("workspace: ", workspace)
//	return workspace
//}
//
//func handleError(task *models.Task, err error) {
//	task.Status = models.StatusFailure
//	task.Error = err.Error()
//	//db.UpdateTask(task)
//	fmt.Println("task--------", task.Workspace)
//	//sendCallback(task)
//}
//
//// LogMessage 定义消息结构体
//type LogMessage struct {
//	Type    string `json:"type"`
//	Content string `json:"content"`
//}
//
//// sendLogToWebSocket 函数用于将日志内容通过 WebSocket 发送到服务端
//func sendLogToWebSocket(url, logLine string, msgType string) {
//	msg := LogMessage{
//		Type:    msgType,
//		Content: logLine,
//	}
//	jsonData, err := json.Marshal(msg)
//	//url := fmt.Sprintf("ws://%s:%s/ssh/agentLogger?executingId=%s", ip, port, executingId)
//	// 尝试连接到 WebSocket 服务端
//	conn, _, err := websocket.DefaultDialer.Dial(url, nil)
//	if err != nil {
//		fmt.Printf("无法连接到 WebSocket 服务器: %v\n", err)
//		return
//	}
//	// 确保在函数结束时关闭连接
//	defer conn.Close()
//
//	// 发送日志行到 WebSocket 服务器
//	fmt.Println(" 发送日志行到 WebSocket 服务器%v", url)
//	err = conn.WriteMessage(websocket.TextMessage, jsonData)
//	if err != nil {
//		fmt.Printf("发送日志到 WebSocket 服务器失败: %v\n", err)
//	}
//}
//
//func tailLog(logPath, serverIP, executeID string, port int, stopChan chan struct{}) {
//	url := fmt.Sprintf("ws://%s:%d/ssh/agentLogger?executingId=%s", serverIP, port, executeID)
//
//	file, err := os.Open(logPath)
//	if err != nil {
//		fmt.Printf("打开日志文件失败: %v\n", err)
//		return
//	}
//	defer file.Close()
//
//	reader := bufio.NewReader(file)
//	lastPosition := int64(0)
//
//	// 启动时立即读取已存在的日志内容
//	info, err := file.Stat()
//	if err == nil && info.Size() > 0 {
//		fmt.Println("检测到已有日志内容，立即读取")
//		readAndSendLogs(reader, file, &lastPosition, url)
//	}
//
//	// 定期检查文件更新
//	ticker := time.Tick(1 * time.Second) // 缩短检测间隔
//
//	for {
//		select {
//		case <-ticker:
//			info, err := file.Stat()
//			if err != nil {
//				fmt.Printf("获取文件状态失败: %v\n", err)
//				continue
//			}
//
//			currentSize := info.Size()
//			if currentSize > lastPosition {
//				fmt.Printf("检测到新日志内容，上次位置: %d, 当前大小: %d\n", lastPosition, currentSize)
//				readAndSendLogs(reader, file, &lastPosition, url)
//			}
//
//		case <-stopChan:
//			fmt.Println("接收到停止信号，开始读取剩余日志")
//
//			// 读取剩余内容
//			for {
//				info, err := file.Stat()
//				if err != nil {
//					fmt.Println("获取文件状态失败，退出日志读取")
//					break
//				}
//
//				currentPos, _ := file.Seek(0, os.SEEK_CUR)
//				if info.Size() <= currentPos {
//					fmt.Println("没有更多日志内容，发送执行完成消息")
//					sendLogToWebSocket(url, "执行完成", "completion")
//					return
//				}
//
//				line, err := reader.ReadString('\n')
//				if err != nil {
//					if err != io.EOF {
//						fmt.Printf("读取日志行失败: %v\n", err)
//					}
//					// 等待一小段时间，可能还有更多数据写入
//					time.Sleep(100 * time.Millisecond)
//					continue
//				}
//
//				fmt.Printf("读取到剩余日志内容: %s\n", line)
//				sendLogToWebSocket(url, line, "log")
//			}
//
//			// 发送完成消息
//			fmt.Println("发送执行完成消息")
//			sendLogToWebSocket(url, "执行完成", "completion")
//			return
//		}
//	}
//}
//
//// 辅助函数：读取并发送日志内容
//func readAndSendLogs(reader *bufio.Reader, file *os.File, lastPosition *int64, url string) {
//	info, err := file.Stat()
//	if err != nil {
//		fmt.Printf("获取文件状态失败: %v\n", err)
//		return
//	}
//
//	currentSize := info.Size()
//	if currentSize <= *lastPosition {
//		return // 没有新内容
//	}
//
//	// 移动到上次读取位置
//	_, err = file.Seek(*lastPosition, os.SEEK_SET)
//	if err != nil {
//		fmt.Printf("无法移动文件指针: %v\n", err)
//		return
//	}
//
//	// 读取并发送所有新行
//	for {
//		line, err := reader.ReadString('\n')
//		if err != nil {
//			if err != io.EOF {
//				fmt.Printf("读取日志行失败: %v\n", err)
//			}
//			break
//		}
//
//		fmt.Printf("读取到新日志内容: %s\n", line)
//		sendLogToWebSocket(url, line, "log")
//	}
//
//	// 更新最后读取位置
//	*lastPosition, _ = file.Seek(0, os.SEEK_CUR)
//}
//func tailLogbak0513(logPath, serverIP, executeID string, port int, stopChan chan struct{}) {
//	//url := fmt.Sprintf("ws://%s:%d/ws/log/%s", serverIP, port, executeID)
//	url := fmt.Sprintf("ws://%s:%d/ssh/agentLogger?executingId=%s", serverIP, port, executeID)
//
//	file, err := os.Open(logPath)
//	if err != nil {
//		fmt.Printf("打开日志文件失败: %v\n", err)
//		return
//	}
//	defer file.Close()
//
//	reader := bufio.NewReader(file)
//	lastPosition := int64(0)
//
//	// 定期检查文件更新
//	ticker := time.Tick(1 * time.Second)
//	for {
//		select {
//		case <-ticker:
//			info, err := file.Stat()
//			if err != nil {
//				fmt.Printf("获取文件状态失败: %v\n", err)
//				continue
//			}
//			currentSize := info.Size()
//			if currentSize > lastPosition {
//				// 有新内容，读取并推送
//				_, err = file.Seek(lastPosition, os.SEEK_SET)
//				if err != nil {
//					fmt.Printf("无法移动文件指针: %v\n", err)
//					continue
//				}
//				for {
//					line, err := reader.ReadString('\n')
//					if err != nil {
//						break
//					}
//					fmt.Printf("读取到新日志内容: %s\n", line)
//					sendLogToWebSocket(url, line, "log")
//				}
//				lastPosition, _ = file.Seek(0, os.SEEK_CUR)
//			}
//		case <-stopChan:
//			// 接收到停止信号，尝试读取剩余的日志内容
//			fmt.Println("接收到停止信号，尝试读取剩余日志")
//
//			// 循环读取直到没有更多内容
//			for {
//				// 移动到文件当前末尾
//				currentPos, _ := file.Seek(0, os.SEEK_CUR)
//				info, err := file.Stat()
//				if err != nil {
//					break
//				}
//
//				// 如果没有新内容，退出循环
//				if info.Size() <= currentPos {
//					break
//				}
//
//				// 读取新内容
//				line, err := reader.ReadString('\n')
//				if err != nil {
//					// 可能是文件末尾，等待一小段时间再试
//					time.Sleep(100 * time.Millisecond)
//					continue
//				}
//
//				fmt.Printf("读取到剩余日志内容: %s\n", line)
//				sendLogToWebSocket(url, line, "log")
//			}
//
//			// 发送完成消息
//			fmt.Println("发送执行完成消息")
//			sendLogToWebSocket(url, "执行完成", "completion")
//			return
//		}
//	}
//}
//
//// tailLog 函数用于监控日志文件并发送日志内容，同时接收停止信号
//func tailLogbak(logPath, serverIP, executeID string, port int, stopChan <-chan struct{}) {
//	url := fmt.Sprintf("ws://%s:%d/ssh/agentLogger?executingId=%s", serverIP, port, executeID)
//	var file *os.File
//	var err error
//	// 尝试打开文件，若失败则重试
//	for {
//		file, err = os.Open(logPath)
//		if err == nil {
//			break
//		}
//		if os.IsNotExist(err) {
//			// 文件不存在，等待一段时间后重试
//			fmt.Printf("日志文件 %s 不存在，等待 1 秒后重试...\n", logPath)
//			time.Sleep(1 * time.Second)
//			continue
//		}
//		fmt.Printf("无法打开文件: %v\n", err)
//		return
//	}
//	defer file.Close()
//
//	// 读取文件现有内容并发送
//	reader := bufio.NewReader(file)
//	for {
//		line, err := reader.ReadString('\n')
//		if err != nil {
//			break
//		}
//		fmt.Printf("读取到日志内容: %s\n", line) // 添加打印读取到的日志内容
//		sendLogToWebSocket(url, line, "log")
//	}
//	// 将文件指针移动到文件末尾
//	lastPosition, err := file.Seek(0, os.SEEK_END)
//	if err != nil {
//		fmt.Printf("无法移动文件指针: %v\n", err)
//		return
//	}
//
//	// 定期检查文件更新
//	ticker := time.Tick(1 * time.Second)
//	for {
//		select {
//		case <-ticker:
//			info, err := file.Stat()
//			if err != nil {
//
//				fmt.Printf("获取文件状态失败: %v\n", err)
//				continue
//			}
//			currentSize := info.Size()
//			if currentSize > lastPosition {
//				// 有新内容，读取并推送
//				_, err = file.Seek(lastPosition, os.SEEK_SET)
//				if err != nil {
//					fmt.Printf("无法移动文件指针: %v\n", err)
//					continue
//				}
//				for {
//					line, err := reader.ReadString('\n')
//					if err != nil {
//						break
//					}
//					fmt.Printf("读取到新日志内容: %s\n", line) // 添加打印读取到的新日志内容
//					//time.Sleep(5 * time.Second)
//					sendLogToWebSocket(url, line, "log")
//				}
//				lastPosition, _ = file.Seek(0, os.SEEK_CUR)
//			}
//		case <-stopChan:
//			// 接收到停止信号，发送完成消息并退出
//			fmt.Printf("读取到执行完成日志内容: %s\n", "completion") // 添加打印读取到的新日志内容
//			sendLogToWebSocket(url, "执行完成", "completion")
//			return
//		}
//	}
//}
//
//// createScriptFile 根据命令内容创建对应的脚本文件
//func createScriptFile(workspace, command, nodeUuid string) (string, error) {
//	// 确定脚本文件名和路径
//
//	// 检查 workspace 路径是否存在
//	if _, err := os.Stat(workspace); os.IsNotExist(err) {
//		return "", fmt.Errorf("指定的工作区路径不存在: %s", workspace)
//	}
//	scriptName := fmt.Sprintf("script_%s", nodeUuid)
//	//scriptName := "script"
//	if setting.Setting.IsWindows {
//		scriptName += ".bat"
//	} else {
//		scriptName += ".sh"
//	}
//	scriptPath := filepath.Join(workspace, scriptName)
//
//	// 根据操作系统创建不同类型的脚本
//	var scriptContent string
//	if setting.Setting.IsWindows {
//		// Windows批处理脚本
//		//cd /d "%s"
//		scriptContent = fmt.Sprintf(`@echo off
//setlocal
//%s
//`, command)
//	} else {
//		// Linux shell脚本
//		//cd "%s"
//		scriptContent = fmt.Sprintf(`#!/bin/bash
//%s
//`, command)
//	}
//
//	// 写入脚本内容
//	err := ioutil.WriteFile(scriptPath, []byte(scriptContent), 0755)
//	if err != nil {
//		return "", fmt.Errorf("创建脚本文件失败: %v", err)
//	}
//
//	fmt.Printf("创建脚本文件: %s\n内容:\n%s\n", scriptPath, scriptContent)
//	return scriptPath, nil
//}
//func prepareCommand(scriptPath string) (*exec.Cmd, error) {
//	// 检查文件是否存在
//	if _, err := os.Stat(scriptPath); os.IsNotExist(err) {
//		return nil, fmt.Errorf("脚本文件不存在: %s", scriptPath)
//	}
//
//	var cmd *exec.Cmd
//	if setting.Setting.IsWindows {
//		// 直接传递路径，exec.Command 会自动处理引号
//		cmd = exec.Command("cmd", "/C", scriptPath)
//
//		// 打印调试信息
//		fmt.Printf("准备执行 Windows 命令: %v\n", cmd.Args)
//		fmt.Printf("脚本路径: %s\n", scriptPath)
//
//		// 验证工作目录
//		workDir := filepath.Dir(scriptPath)
//		if _, err := os.Stat(workDir); os.IsNotExist(err) {
//			return nil, fmt.Errorf("工作目录不存在: %s", workDir)
//		}
//	} else {
//		cmd = exec.Command("bash", scriptPath)
//		fmt.Printf("准备执行 Linux 命令: %v\n", cmd.Args)
//	}
//
//	// 设置工作目录
//	//cmd.Dir = filepath.Dir(scriptPath)
//	// 设置环境变量
//	cmd.Env = os.Environ()
//	cmd.Env = append(cmd.Env, "GITEA_RUNNER=true")
//
//	return cmd, nil
//}
//func prepareCommandbak0513(scriptPath string) (*exec.Cmd, error) {
//	// 检查文件是否存在
//	if _, err := os.Stat(scriptPath); os.IsNotExist(err) {
//		return nil, fmt.Errorf("脚本文件不存在: %s", scriptPath)
//	}
//	fmt.Println("-----------------脚本文件存在", scriptPath)
//	var cmd *exec.Cmd
//	if setting.Setting.IsWindows {
//		quotedPath := fmt.Sprintf(`"%s"`, scriptPath)
//		cmd = exec.Command("cmd", "/C", quotedPath)
//		// 执行Windows批处理脚本
//		//cmd = exec.Command("cmd", "/C", scriptPath)
//	} else {
//		// 执行Linux shell脚本
//		cmd = exec.Command("bash", scriptPath)
//	}
//
//	// 设置环境变量
//	cmd.Env = os.Environ()
//	cmd.Env = append(cmd.Env, fmt.Sprintf("devops-runner=true"))
//	// 设置工作目录
//	cmd.Dir = filepath.Dir(scriptPath)
//
//	// 打印调试信息
//	fmt.Printf("准备执行命令: %v\n", cmd.Args)
//	fmt.Printf("工作目录: %s\n", cmd.Dir)
//	fmt.Printf("环境变量 PATH: %s\n", os.Getenv("PATH"))
//	return cmd, nil
//}
//func prepareCommandbak(cmdStr string) (*exec.Cmd, error) {
//	var cmd *exec.Cmd
//	if setting.Setting.IsWindows {
//		fmt.Println("--cmdstr------", cmdStr)
//		cmd = exec.Command("cmd", "/C", cmdStr)
//	} else {
//		cmd = exec.Command("bash", "-c", cmdStr)
//	}
//
//	// 设置环境变量
//	cmd.Env = os.Environ()
//	cmd.Env = append(cmd.Env, fmt.Sprintf("GITEA_RUNNER=true"))
//
//	// 处理 Windows 下的 git 命令格式
//	if setting.Setting.IsWindows {
//		cmdStr = strings.Replace(cmdStr, "-", " ", 1)
//	}
//
//	return cmd, nil
//}
//
//func NewIRunnerService() IRunnerService {
//	return &RunnerService{}
//}
//
//type IRunnerService interface {
//	Execute(req dto.RunnerPipeline) (int64, interface{}, error)
//}
